// 1.Pick 选取一些类型使用
// 2.Uppercase 构造一个 Type 的所有属性都设置为大写的类型。
// 3.Lowercase 构造一个 Type 的所有属性都设置为小写的类型，与大写相反。
// 4.Capitalize 构造一个将 Type 的所有属性设置为大写的类型。
// 5.Uncapitalize 构造一个将 Type 的所有属性设置为 uncapitalize 的类型，与首字母大写相反。
// 6.Partial 构造一个类型，其中 Type 的所有属性都设置为可选。
// 7.Required 构造一个类型，该类型由设置为 required 的 Type 的所有属性组成，Opposite的对面。
// 8.Readonly 构造一个类型，该类型由设置为只读的 Type 的所有属性组成。
// 9.Record 构造一个具有一组类型 T 的属性 K 的类型，每个属性 K 都映射到类型 T。
// 10.Omit其键在联合类型键中的 Type 属性。
// 11.Exclude 构造一个具有 Type 的所有属性的类型，除了键在联合类型 Excluded 中的那些。
// 12.Extract 构造一个具有 Type 的所有属性的类型，其键在联合类型 Extract 中。
// 13.NonNullable 构造一个类型，其中 Type 的所有属性都设置为不可为空。
// 14.映射类型
// 15.条件类型


export { };
// 1.Pick 选取一些类型使用
// 用户配置文件响应
interface UserProfileRes {
  id: number;
  name: string;
  email: string;
  phone: string;
  avatar: string;
};
// 登录响应
// interface LoginRes {
//   id: number;
//   name: string;
// };

// 我们可以为 UserProfileRes 定义类型并为 LoginRes 选择一些属性，
// 而不是定义相同上下文 LoginRes 和 UserProfileRes 的类型。
type LoginRes = Pick<UserProfileRes, "id" | "name">;



// 2.Uppercase 构造一个 Type 的所有属性都设置为大写的类型。
type Role = "admin" | "user" | "guest";

// Bad practice
// type UppercaseRole = "ADMIN" | "USER" | "GUEST";

// Good practice 
type UppercaseRole = Uppercase<Role>;


// 3.Lowercase 构造一个 Type 的所有属性都设置为小写的类型，与大写相反。
type Roles = "ADMIN" | "USER" | "GUEST";

// Bad practice
// type LowercaseRole = "admin" | "user" | "guest";

// Good practice 
type LowercaseRole = Lowercase<Roles>; // "admin" | "user" | "guest"



// 4.Capitalize 构造一个将 Type 的所有属性设置为大写的类型。
type Role2 = "admin" | "user" | "guest";

// Bad practice 
// type CapitalizeRole = "Admin" | "User" | "Guest";

// Good practice 
type CapitalizeRole = Capitalize<Role2>; // "Admin" | "User" | "Guest"



// 5.Uncapitalize 构造一个将 Type 的所有属性设置为 uncapitalize 的类型，与首字母大写相反。
type Role5 = "Admin" | "User" | "Guest";

// Bad practice 
// type UncapitalizeRole5 = "admin" | "user" | "guest";

// Good practice 
type UncapitalizeRole5 = Uncapitalize<Role5>; // "admin" | "user" | "guest"



// 6.Partial 构造一个类型，其中 Type 的所有属性都设置为可选。
interface User {
  name: string;
  age: number;
  password: string;
}

// Bad practice
// interface PartialUser {
//   name?: string;
//   age?: number;
//   password?: string;
// }

// Good practice 
type PartialUser = Partial<User>;



// 7.Required 构造一个类型，该类型由设置为 required 的 Type 的所有属性组成，Opposite的对面。
interface User7 {
  name?: string;
  age?: number;
  password?: string;
}

// Bad practice
// interface RequiredUser {
//   name: string;
//   age: number;
//   password: string;
// }

// Good practice 
type RequiredUser = Required<User7>;



// 8.Readonly 构造一个类型，该类型由设置为只读的 Type 的所有属性组成。
interface User8 {
  role: string;
}

// Bad practice
// const user1: User8 = { role: "ADMIN" };
// user1.role = "USER";

// Good practice
const user2: Readonly<User8> = { role: "ADMIN" };
// 此时不能修改 user2 对象中的属性了
// user2.role = "USER";
// Error: Cannot assign to 'role' because it is a read-only property.



// 9.Record 构造一个具有一组类型 T 的属性 K 的类型，每个属性 K 都映射到类型 T。
interface Address {
  street: string;
  pin: number;
}
// interface Addresses {
//   home: Address;
//   office: Address;
// }
// Good practice
type AddressesRecord = Record<"home" | "office", Address>;



// 10.Omit其键在联合类型键中的 Type 属性。
interface User {
  name: string;
  age: number;
  password: string;
}

// Bad practice
// interface UserPartial {
//   name: string;
//   age: number;
// }

// Good practice 
type UserPartial = Omit<User, "password">;



// 11.Exclude 构造一个具有 Type 的所有属性的类型，除了键在联合类型 Excluded 中的那些。
type Role11 = "ADMIN" | "USER" | "GUEST";
// Bad practice 
type NonAdminRole = "USER" | "GUEST";
// Good practice 
type NonAdmin = Exclude<Role11, "ADMIN">; // "USER" | "GUEST"



// 12.Extract 构造一个具有 Type 的所有属性的类型，其键在联合类型 Extract 中。
type Role12 = "ADMIN" | "USER" | "GUEST";
// Bad practice
// type AdminRole = "ADMIN";

// Good practice 
type Admin = Extract<Role12, "ADMIN">; // "ADMIN"



// 13.NonNullable 构造一个类型，其中 Type 的所有属性都设置为不可为空。
type Role13 = "ADMIN" | "USER" | null;
// Bad practice
// type NonNullableRole = "ADMIN" | "USER";

// Good practice 
type NonNullableRole = NonNullable<Role13>; // "ADMIN" | "USER"



// 14.映射类型
type Readonly<T> = {
  readonly [k in keyof T]: T[k];
};
interface Point {
  x: number;
  y: number;
};
type ReadonlyPoint = Readonly<Point>;
/* 
我们定义了一个叫做 Readonly 的映射类型，它以类型 T 为泛型参数，并使其所有属性成为只读。
然后，我们创建了一个 ReadonlyPoint 类型，该类型基于 Point 接口，其中所有属性都是只读的。
*/
let pot: ReadonlyPoint = {
  x: 100,
  y: 100
};
// pot.x = 99;  //此处报错


// 条件类型
// 条件类型允许您根据条件创建新类型。语法类似于三元运算符，使用extends关键字作为类型约束
type NonNullable<T> = T extends null | undefined ? never : T;
// 在此示例中，我们定义了一个名为NonNullable的条件类型，它取一个类型T并检查它是否扩展了null或undefined。
// 如果扩展了，则结果类型为never，否则为原始类型T。